package com.study.shiro.config;

import com.study.shiro.entity.Perm;
import com.study.shiro.entity.User;
import com.study.shiro.service.IUserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;

/**
 * 自定义 Realm, 如果为了提高性能可以把数据放入 redis, 两种方式 1: 业务层手写, 2: 使用 shiro-redis 工具(本项目使用这种方式)
 *
 * @author huanggy
 * @date 2020/2/9 16:52
 */
public class CustomerRealm extends AuthorizingRealm {

    @Autowired
    private IUserService userService;

    // 授权(检测权限)
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        // 使用缓存
        User cacheUser = (User) principalCollection.getPrimaryPrincipal();
        User user = userService.selectAllInfoByUsername(cacheUser.getUsername());

        // 不使用缓存
        // String username = (String)principalCollection.getPrimaryPrincipal();
        // User user = userService.selectAllInfoByUsername(username);

        // 获取用户的角色和权限
        ArrayList<String> roleList = new ArrayList<>();
        ArrayList<String> permList = new ArrayList<>();
        user.getRoles().forEach(item -> {
            roleList.add(item.getName());
            List<Perm> perms = item.getPerms();
            perms.forEach(item2 -> permList.add(item2.getCode()));
        });

        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.addRoles(roleList);
        simpleAuthorizationInfo.addStringPermissions(permList);

        return simpleAuthorizationInfo;
    }

    // 认证(登录校验)
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 从 token 中解析用户信息
        String username = (String) authenticationToken.getPrincipal();
        // selectByUsername 方法里可以接入 redis
        User user = userService.selectByUsername(username);
        // 认证失败
        if (user == null) {
            return null;
        }

        // 不使用缓存
        // return new SimpleAuthenticationInfo(username, user.getPassword(), this.getName());

        // 使用缓存
        return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), this.getName());
    }
}
